package com.gs.wechatdemo.audio;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.PowerManager;


import com.gs.wechatdemo.MyApplication;

import java.io.IOException;

public class AudioPlayManager implements SensorEventListener {

    private static volatile AudioPlayManager instance;
    private IAudioPlayListener mPlayListener;
    private String mPlayUrl;
    private Sensor mSensor;
    private SensorManager mSensorManager;
    private MediaPlayer mMediaPlayer;
    private AudioManager mAudioManager;
    private PowerManager mPowerManager;
    private PowerManager.WakeLock mWakeLock;
    private AudioManager.OnAudioFocusChangeListener mAFChangeListener;

    public static AudioPlayManager getInstance() {
        if (instance == null) {
            synchronized (AudioPlayManager.class) {
                if (instance == null) {
                    instance = new AudioPlayManager();
                }
            }
        }
        return instance;
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        try {
            float range = event.values[0];
            if (mSensor != null && mMediaPlayer != null) {
                if (mMediaPlayer.isPlaying()) {
                    if ((double) range > 0.0D) {
                        if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) {
                            return;
                        }

                        mAudioManager.setMode(AudioManager.MODE_NORMAL);
                        mAudioManager.setSpeakerphoneOn(true);
                        final int position = mMediaPlayer.getCurrentPosition();
                        mMediaPlayer.reset();
                        mMediaPlayer.setAudioStreamType(3);
                        mMediaPlayer.setVolume(1.0f, 1.0f);
                        mMediaPlayer.setDataSource(mPlayUrl);
                        mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                            @Override
                            public void onPrepared(MediaPlayer mp) {
                                mp.seekTo(position);
                            }
                        });
                        mMediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
                            @Override
                            public void onSeekComplete(MediaPlayer mp) {
                                mp.start();
                            }
                        });
                        mMediaPlayer.prepareAsync();
                        setScreenOn();
                    } else {
                        setScreenOff();
                        if (mAudioManager.getMode() == AudioManager.MODE_IN_COMMUNICATION) {
                            return;
                        }
                        mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
                        mAudioManager.setSpeakerphoneOn(false);
                        replay();
                    }
                } else if ((double) range > 0.0D) {
                    if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) {
                        return;
                    }
                    mAudioManager.setMode(AudioManager.MODE_NORMAL);
                    mAudioManager.setSpeakerphoneOn(true);
                    setScreenOn();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void replay() {
        try {
            mMediaPlayer.reset();
            mMediaPlayer.setAudioStreamType(0);
            mMediaPlayer.setVolume(1.0F, 1.0F);
            mMediaPlayer.setDataSource(mPlayUrl);
            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.start();
                }
            });
            mMediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void setScreenOff() {
        if (mWakeLock == null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mWakeLock = mPowerManager.newWakeLock(32, "Hkpc:AudioPlayManager");
            }
        }
        if (mWakeLock != null) {
            mWakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
        }
    }

    private void setScreenOn() {
        if (mWakeLock != null) {
            mWakeLock.setReferenceCounted(false);
            mWakeLock.release();
            mWakeLock = null;
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    public void startPlay(final String url, IAudioPlayListener playListener) {
        try {
            if (url != null) {
                if (playListener != null && mPlayUrl != null) {
                    playListener.onStop(url);
                }

                resetMediaPlayer();
                mAFChangeListener = new AudioManager.OnAudioFocusChangeListener() {
                    @Override
                    public void onAudioFocusChange(int focusChange) {
                        if (mAudioManager != null && focusChange == -1) {
                            mAudioManager.abandonAudioFocus(mAFChangeListener);
                            mAFChangeListener = null;
                            resetMediaPlayer();
                        }
                    }
                };
                mPowerManager = (PowerManager) MyApplication.getContext().getSystemService(Context.POWER_SERVICE);
                mAudioManager = (AudioManager) MyApplication.getContext().getSystemService(Context.AUDIO_SERVICE);
                if (!mAudioManager.isWiredHeadsetOn()) {
                    mSensorManager = (SensorManager) MyApplication.getContext().getSystemService(Context.SENSOR_SERVICE);
                    mSensor = mSensorManager.getDefaultSensor(8);
                    mSensorManager.registerListener(this, mSensor, 3);
                }
                muteAudioFocus(mAudioManager, true);
                mPlayListener = playListener;
                mMediaPlayer = new MediaPlayer();
                mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        if (mPlayListener != null) {
                            mPlayListener.onComplete(url);
                            mPlayListener = null;
                        }
                        reset();
                    }
                });
                mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
                    @Override
                    public boolean onError(MediaPlayer mp, int what, int extra) {
                        reset();
                        return true;
                    }
                });

                mMediaPlayer.setDataSource(url);
                mMediaPlayer.setAudioStreamType(3);
                mMediaPlayer.prepare();
                mMediaPlayer.start();

                if (mPlayListener != null) {
                    mPlayListener.onStart(url);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            if (mPlayListener != null) {
                mPlayListener.onStop(url);
                mPlayListener = null;
            }
            reset();
        }
    }

    public void stopPlay() {
        reset();
    }

    private void reset() {
        resetMediaPlayer();
        resetAudioPlayManager();
    }

    private void resetAudioPlayManager() {
        if (mAudioManager != null) {
            muteAudioFocus(mAudioManager, false);
        }

        if (mSensorManager != null) {
            mSensorManager.unregisterListener(this);
        }

        mSensorManager = null;
        mSensor = null;
        mPowerManager = null;
        mAudioManager = null;
        mWakeLock = null;
        mPlayListener = null;
        mPlayUrl = null;
    }

    private void muteAudioFocus(AudioManager audioManager, boolean bMute) {
        if (bMute) {
            audioManager.requestAudioFocus(mAFChangeListener, 3, 2);
        } else {
            audioManager.abandonAudioFocus(mAFChangeListener);
            mAFChangeListener = null;
        }
    }

    private void resetMediaPlayer() {
        try {
            if (mMediaPlayer != null) {
                mMediaPlayer.stop();
                mMediaPlayer.reset();
                mMediaPlayer.release();
                mMediaPlayer = null;
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }
}
